package com.bowen.demo.demo001.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * <h3>java-study</h3>
 * <p>使用Callable和Future接口创建线程</p>
 * @author : zhang.bw
 * @date : 2020-09-18 10:12
 **/
public class MyCallable {

	/**
	 * 创建Callable接口的实现类MyCallableTest ，并实现Call方法
	 * 创建Callable实现类的实现，使用FutureTask类包装Callable对象，该FutureTask对象封装了Callable对象的Call方法的返回值
	 * 使用FutureTask对象作为Thread对象的target创建并启动线程
	 * 调用FutureTask对象的get()来获取子线程执行结束的返回值
	 */

	/**
	 * 测试方法
	 * @param args
	 */
	public static void main(String[] args) {
		new MyCallable().test();
	}

	public void test() {

		// 创建MyCallableTest对象
		Callable<Integer> myCallableTest = new MyCallableTest();
		//使用FutureTask来包装MyCallableTest对象
		FutureTask<Integer> ft = new FutureTask<Integer>(myCallableTest);

		for (int i = 0; i < 10; i++) {
			System.out.println("test "+Thread.currentThread().getName() + " " + i);
			if (i == 3) {
				//FutureTask对象作为Thread对象的target创建新的线程
				Thread thread = new Thread(ft);
				//线程进入到就绪状态
				thread.start();
			}
		}

		System.out.println("主线程for循环执行完毕..");

		try {
			//取得新创建的新线程中的call()方法返回的结果
			int sum = ft.get();
			System.out.println("sum = " + sum);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 在实现Callable接口中，此时不再是run()方法了，而是call()方法，此call()方法作为线程执行体，
	 * 同时还具有返回值！在创建新的线程时，是通过FutureTask来包装MyCallableTest对象，同时作为了Thread对象的target。
	 */
	class MyCallableTest implements Callable<Integer> {
		private int i = 0;

		// 与run()方法不同的是，call()方法具有返回值
		@Override
		public Integer call() {
			int sum = 0;
			for (; i < 10; i++) {
				System.out.println("MyCallableTest "+Thread.currentThread().getName() + " " + i);
				sum += i;
			}
			return sum;
		}

	}
}